package com.ysjweb.dish.Service;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ysjweb.dish.Service.impl.GetWeather;
import com.ysjweb.dish.pojo.WeatherFather;
import com.ysjweb.dish.pojo.WeatherForcast;
import com.ysjweb.dish.pojo.WeatherHistorical;
import com.ysjweb.dish.pojo.WeatherNow;
import com.ysjweb.dish.tool.HeFengApiJwt;
import com.ysjweb.dish.tool.GzipResponseExtractor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.HttpServerErrorException;
import org.springframework.web.client.RestTemplate;


import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;

import org.springframework.http.HttpHeaders;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;

@Slf4j
@Service
public class WeatherService implements GetWeather {

    // 注入和风天气API密钥（从配置文件读取）
//    private static String apiKey="ccae2f057ccd4912bd502aadb0835faa";
    private static final String apiHost="kn46h28qra.re.qweatherapi.com";
    // 天气API基础URL
    private static final String BASE_URL = "https://"+apiHost+"/v7/weather";//devapi.qweather.com
    // 地理编码API基础URL（用于位置解析）
    private static final String GEO_URL = "https://"+apiHost+"/geo/v2/city/lookup";//geoapi.qweather.com

    // WebClient实例用于发送HTTP请求
//    private final WebClient webClient;
    // Jackson ObjectMapper用于JSON解析
    private final ObjectMapper objectMapper;

    private final RestTemplate restTemplate;



    @Autowired
    public WeatherService(RestTemplate restTemplate, ObjectMapper objectMapper) {
        // 创建WebClient实例
//        this.webClient = webClientBuilder.build();
        // 注入ObjectMapper实例
        this.objectMapper = objectMapper;
        this.restTemplate = restTemplate;
    }

    @Override
    public WeatherFather getCurrentWeather(String location) {
        // 调用内部方法获取实时天气数据
        return getWeatherData(location, "now");
    }

    @Override
    public WeatherFather getForecastWeather(String location, int days) {
        return getWeatherData(location, "d"+ days);
    }


    @Override
    public WeatherFather getHistoricalWeather(String location, LocalDate date) {
        // 将日期格式化为yyyyMMdd格式
        String dateStr = date.format(DateTimeFormatter.BASIC_ISO_DATE);
        return getWeatherData(location, "historical/" + dateStr);
    }
    private WeatherFather getWeatherData(String location, String endpoint) throws RuntimeException {
        // 解析位置ID
        String locationId = resolveLocationId(location);
        //请求头
        String jwt;
        try {
            jwt=HeFengApiJwt.generateJwt();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        HttpHeaders headers = new HttpHeaders();
        headers.setBearerAuth(jwt);
        // 构建API URL
        String encodedLocation = URLEncoder.encode(locationId, StandardCharsets.UTF_8);
        String apiUrl;
        if(endpoint.contains("historical")){
            int index=endpoint.indexOf("/");
            String date=endpoint.substring(index+1);
            apiUrl=String.format("https://"+apiHost+"/v7/historical/weather?location=%s&date=%s", encodedLocation, date);
        }else if(endpoint.contains("now")){
            apiUrl = String.format("%s/%s?location=%s",
                    BASE_URL, endpoint, encodedLocation);
        }else {
            int index=endpoint.indexOf("d");
            String date=endpoint.substring(index+1);
            int day=Integer.parseInt(date);
            int day2;
            if(day>15){
                day2=30;
            }else if(day>10){
                day2=15;
            }else if(day>7){
                day2=10;
            }else if(day>3){
                day2=7;
            }else{
                day2=3;
            }
            apiUrl=String.format("%s/%sd?location=%s",BASE_URL,day2,encodedLocation);
        }
        //发送请求
        try {
//            HttpEntity<String> entity=new HttpEntity<>(headers);
//            // 4. 发送HTTP GET请求
//            ResponseEntity<String> response = restTemplate.exchange(
//                    apiUrl,
//                    HttpMethod.GET,
//                    entity,
//                    String.class
//            );
//
//            if (response.getStatusCode() != HttpStatus.OK) {
//                throw new WeatherApiException("API请求失败: " + response.getStatusCode());
//            }
            // 解析JSON响应
            String transform=restTemplate.execute(apiUrl, HttpMethod.GET,
                    request -> {
                        // 添加必要的请求头
                        request.getHeaders().putAll(headers); // 添加JWT等头
                        request.getHeaders().set("Accept-Encoding", "gzip");
                    },
                    new GzipResponseExtractor());

            JsonNode rootNode = objectMapper.readTree(transform);
            // 转换为WeatherData对象
            return parseWeatherResponse(rootNode, endpoint);
        }
        catch (HttpClientErrorException e) {
            throw new RuntimeException("客户端错误: " + e.getStatusCode() + " - " + e.getResponseBodyAsString());
        }
        catch (HttpServerErrorException e) {
            throw new RuntimeException("服务器错误: " + e.getStatusCode() + " - " + e.getResponseBodyAsString());
        }
        catch (Exception e) {
            throw new RuntimeException("请求处理失败: " + e.getMessage());
        }
    }
    private String resolveLocationId(String location) throws RuntimeException {
        // 如果输入已经是数字ID（如"101010100"），直接返回
        if (location.matches("\\d+")) {
            return location;
        }
        log.info("请求和风天气API，参数: location={}", location);
        //请求头
        String jwt;
        try {
            jwt=HeFengApiJwt.generateJwt();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        HttpHeaders headers = new HttpHeaders();
        headers.setBearerAuth(jwt);
        //构建API URL
        String geoApiUrl = String.format("%s?location=%s", GEO_URL, location);
        try {
//            HttpEntity<String> entity=new HttpEntity<>(headers);
//            // 发送地理编码API请求
//            ResponseEntity<String> response = restTemplate.exchange(
//                    geoApiUrl,
//                    HttpMethod.GET,
//                    entity,
//                    String.class
//            );
            String transform=restTemplate.execute(geoApiUrl, HttpMethod.GET,
                    request -> {
                        // 添加必要的请求头
                        request.getHeaders().putAll(headers); // 添加JWT等头
                        request.getHeaders().set("Accept-Encoding", "gzip");
                    },
                    new GzipResponseExtractor());
            // 检查HTTP状态码
//            if (response.getStatusCode() != HttpStatus.OK) {
//                throw new WeatherApiException("位置解析失败: " + response.getStatusCode());
//            }
            // 解析JSON响应
            JsonNode rootNode = objectMapper.readTree(transform);
            // 从响应中提取位置ID
            return extractLocationId(rootNode);
        }
        catch (Exception e) {
            throw new RuntimeException("位置解析失败: " + e.getMessage());
        }
    }

    private String extractLocationId(JsonNode geoResponse) {
        // 获取"location"节点
        JsonNode locations = geoResponse.path("location");
        if (!locations.isArray() || locations.isEmpty()) {
            throw new RuntimeException("未找到匹配的位置");
        }
        return locations.get(0).path("id").asText();
    }

    private WeatherFather parseWeatherResponse(JsonNode response, String endpoint) throws RuntimeException {
        String code = response.path("code").asText();
        if (!"200".equals(code)) {
            String errorMsg = response.path("message").asText();
            throw new RuntimeException("API错误: " + errorMsg);
        }
        if ("now".equals(endpoint)) {
            return parseCurrentWeather(response);
        } else if (endpoint.contains("d")) {
            return parseForecastWeather(response, endpoint);
        } else if (endpoint.contains("historical")) {
            return parseHistoricalWeather(response);
        } else {
            throw new RuntimeException("不支持的端点类型: " + endpoint);
        }
    }

    private WeatherNow parseCurrentWeather(JsonNode response) {
        // 获取"now"节点
        JsonNode nowNode = response.path("now");
        // 构建并返回天气数据对象
        return WeatherNow.builder()
                .temp(nowNode.path("temp").asInt()) // 温度
                .text(nowNode.path("text").asText()) // 天气状况
                .build();
    }

    private WeatherForcast parseForecastWeather(JsonNode response, String days) {
        // 获取"daily"节点（包含多天预报）
        JsonNode dailyNode = response.path("daily");
        if (!dailyNode.isArray() || dailyNode.isEmpty()) {
            throw new RuntimeException("无效的预报数据");
        }
        int requestedDays = Integer.parseInt(days.replace("d", ""));
        JsonNode dayData = dailyNode.get(requestedDays - 1);
        return WeatherForcast.builder()
                .tempMax(dayData.path("tempMax").asInt())
                .tempMin(dayData.path("tempMin").asInt())
                .textDay(dayData.path("textDay").asText())
                .build();
    }
    private WeatherHistorical parseHistoricalWeather(JsonNode response) {
        String code = response.path("code").asText();
        if (!"200".equals(code)) {
            String errorMsg = response.path("message").asText();
            throw new RuntimeException("API错误: " + errorMsg);
        }

        JsonNode dailyNode = response.path("weatherHourly");
        if (!dailyNode.isArray() || dailyNode.isEmpty()) {
            throw new RuntimeException("无效的历史数据");
        }
        JsonNode dayData = dailyNode.get(0);
        log.info(dayData.toString());
        return WeatherHistorical.builder()
                .tempMax(dayData.path("temp").asInt()) // 最高温度
                .tempMin(dayData.path("temp").asInt())
                .text(dayData.path("text").asText()) // 天气状况
                .build();
    }
}




